package com.or.util;

/**
 * @author wei
 * @date 2025/2/27 16:52
 */

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.Map;

/**
 * Token工具类，用于生成和验证JWT令牌。
 */
@Slf4j
public class TokenUtil {

    /**
     * JWT加密的密钥。
     */
    private static final String ENCRYPT_KEY = "suijimiyao&jwt";

    /**
     * JWT令牌的过期时间，单位为分钟。
     */
    private static final int EXPIRE_TIME = 60;

    /**
     * JWT令牌的发行者。
     */
    private static final String ISSUER = "bawangchaji";

    /**
     * 生成JWT令牌。
     *
     * @param json 令牌中承载的信息，以JSONObject形式提供。
     * @return 生成的JWT令牌字符串。
     */
    public static String createToken(JSONObject json) {

        // 使用JWT创建一个令牌
        return JWT.create()
                // 设置令牌的主题，即json对象转换后的字符串 不要把密码封装进去，不安全
                .withSubject(json.toString())
                // 设置令牌的发行者
                .withIssuer(ISSUER)
                // 设置令牌的过期时间，以当前时间为基础加上设定的过期时间
                .withExpiresAt(DateUtil.offsetMinute(new Date(), EXPIRE_TIME))
                // 设置自定义的声明，这里以"test"为键，"123"为值
                .withClaim("userInfo", json)
                // 使用HMAC256算法对令牌进行签名加密
                .sign(Algorithm.HMAC256(ENCRYPT_KEY));
    }

    /**
     * 是否需要重新生成token（为了延长token时长)
     */
    public static boolean needCreate(String token) {
        //创建token验证器
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(ENCRYPT_KEY)).withIssuer(ISSUER).build();
        DecodedJWT decodedJWT = jwtVerifier.verify(token);
        //获取过期时间
        Date timeoutDate = decodedJWT.getExpiresAt();
        //获取过期时间与当前时间的时间差（毫秒）
        long diffTime = timeoutDate.getTime() - new Date().getTime();
        log.info("过期时间与当前时间的时间差（毫秒）:" + diffTime);
        if (diffTime > 20 * 60 * 1000) {
            //不需要更新
            return false;
        } else {
            //token距离过期小于5分钟，需要更新
            return true;
        }
    }


    /**
     * 验证JWT令牌的有效性。
     *
     * @param token 待验证的JWT令牌字符串。
     * @return 如果令牌有效，则返回true；否则返回false。
     */
    public static boolean verifyToken(String token) {
        try {
            // 创建一个 JWT 验证器，使用 HMAC256 算法，密钥为 ENCRYPT_KEY，发行者为 ISSUER
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(ENCRYPT_KEY))
                    .withIssuer(ISSUER)
                    .build();
            // 对令牌进行验证
            jwtVerifier.verify(token);
            // 如果验证成功，返回 true
            return true;
        } catch (Exception e) {
            // 验证失败，打印异常信息，并返回false
            e.printStackTrace();
            return false;
        }
    }

    public static String refreshToken(String token) {
        DecodedJWT a = JWT.require(Algorithm.HMAC256(ENCRYPT_KEY)).build().verify(token);
        Map<String, Claim> claims = a.getClaims();
        return createToken(new JSONObject(claims));
    }
}